package avicit.bdp.dcs.semistructure.rest;

import avicit.bdp.common.dto.upload.ResumeUploadDto;
import avicit.bdp.common.service.service.FileCommonService;
import avicit.bdp.common.utils.redis.RedisCacheHelper;
import avicit.bdp.dcs.semistructure.dto.CatalogAndFileDto;
import avicit.bdp.dcs.semistructure.dto.CatalogDto;
import avicit.bdp.dcs.semistructure.dto.CatalogTemplateDTO;
import avicit.bdp.dcs.semistructure.dto.FileDto;
import avicit.bdp.dcs.semistructure.service.DcsFileService;
import avicit.bdp.dcs.tools.dto.UploadData;
import avicit.platform6.core.rest.msg.ResponseMsg;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/api/bdp/dcs/file/FileRest")
@Api(tags = "文件管理接口")
public class FileRest {

    private static final Logger logger = LoggerFactory.getLogger(FileRest.class);

    @Autowired
    private DcsFileService fileService;
    @Autowired
    private FileCommonService fileCommonService;
    @Autowired
    private RedisCacheHelper redisCacheHelper;


    @PostMapping("/upload")
    @ApiOperation(value = "文件上传")
    public ResponseMsg<String> upload(@ApiParam(value = "UploadFile", name = "UploadFile") ResumeUploadDto resumeUploadDto, HttpServletResponse response) throws Exception {
        ResponseMsg<String> responseMsg = new ResponseMsg<>();
        Long startTime = System.currentTimeMillis();

        try {
            fileCommonService.upload(resumeUploadDto);
        } catch (Exception e) {
            response.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
            responseMsg.setErrorDesc(e.getMessage());
            logger.error(e.getMessage(), e);
        }

        Long endTime = System.currentTimeMillis();
        logger.info("上传文件{}--{}/{}，开始时间：{}，结束时间：{}，耗时：{}", resumeUploadDto.getFile().getOriginalFilename(), resumeUploadDto.getChunk(), resumeUploadDto.getChunks(), startTime, endTime, endTime - startTime);

        return responseMsg;
    }

    @PostMapping("/saveUploadInfo")
    @ApiOperation(value = "保存文件上传信息(文件关联模板)")
    public ResponseMsg<String> saveUploadInfo(@RequestBody CatalogTemplateDTO catalogTemplateDTO, HttpServletResponse response) throws Exception {
        ResponseMsg<String> responseMsg = new ResponseMsg<>();

        try {
            fileService.saveUploadInfo(catalogTemplateDTO);
        } catch (Exception e) {
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            responseMsg.setErrorDesc(e.getMessage());
            logger.error(e.getMessage(), e);
        }
        return responseMsg;
    }

    @GetMapping("/getProgress")
    @ApiOperation(value = "获取文件上传进度")
    public ResponseMsg<Map<String, String>> getProgress(
            @ApiParam(value = "hdfsPath", name = "hdfsPath") @RequestParam String hdfsPath,
            @ApiParam(value = "fileName", name = "fileName") @RequestParam String fileName) throws Exception {
        ResponseMsg<Map<String, String>> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(fileCommonService.getProgress(hdfsPath, fileName));
        return responseMsg;
    }

    @PostMapping("/mergeChunks")
    @ApiOperation(value = "获取文件上传是否成功，成功，暂停，失败的话响应，否则等待")
    public ResponseMsg<Map<String, String>> mergeChunks(@RequestBody ResumeUploadDto resumeUploadDto) throws Exception {
        ResponseMsg<Map<String, String>> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(fileCommonService.mergeChunks(resumeUploadDto));
        return responseMsg;
    }

    @GetMapping("/upload")
    @ApiOperation(value = "获取已经上传的分片信息")
    public ResponseMsg<Map<String, List<Integer>>> getUploadedChunkInfoList(
            @ApiParam(value = "文件唯一标识", name = "fileMd5", required = true) @RequestParam String fileMd5,
            @ApiParam(value = "hdfsPath", name = "hdfsPath") @RequestParam String hdfsPath,
            @ApiParam(value = "fileName", name = "fileName") @RequestParam String fileName) throws Exception {
        ResponseMsg<Map<String, List<Integer>>> responseMsg = new ResponseMsg<>();
        Long startTime = System.currentTimeMillis();
        responseMsg.setResponseBody(fileCommonService.getUploadedChunkInfos(fileMd5, hdfsPath, fileName));
        Long endTime = System.currentTimeMillis();
        logger.info("开始时间：{}，结束时间：{}，耗时：{}", startTime, endTime, endTime - startTime);
        return responseMsg;
    }

    @DeleteMapping("/deleteFileUpload")
    @ApiOperation(value = "删除文件上传")
    public ResponseMsg<Boolean> deleteFileUpload(@RequestBody ResumeUploadDto resumeUploadDto) throws Exception {
        ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(fileCommonService.deleteFileUpload(resumeUploadDto.getFileMd5(), resumeUploadDto.getHdfsPath(),
                resumeUploadDto.getFileName()));
        return responseMsg;
    }

    @GetMapping("/pauseFileUpload")
    @ApiOperation(value = "暂停文件上传")
    public ResponseMsg<Boolean> pauseFileUpload(@ApiParam(value = "hdfsPath", name = "hdfsPath") @RequestParam String hdfsPath,
                                                @ApiParam(value = "fileName", name = "fileName") @RequestParam String fileName) throws Exception {
        ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(fileCommonService.pauseFileUpload(hdfsPath, fileName));
        return responseMsg;
    }

    @PostMapping("/batchUpload")
    @ApiOperation(value = "批量采集本地目录下指定类型数据至hdfs")
    public ResponseMsg<String> batchUpload(@RequestBody UploadData uploadData) throws Exception {
        ResponseMsg<String> responseMsg = new ResponseMsg<>();
        fileService.batchUpload(uploadData.getSrcPath(), uploadData.getHdfsPath(), uploadData.getType());
        return responseMsg;
    }

    @GetMapping("/getFileList")
    @ApiOperation(value = "查询文件列表")
    public ResponseMsg<List<FileDto>> getFileList(@ApiParam(value = "文件名称", name = "fileName") @RequestParam(required = false) String fileName,
                                                  @ApiParam(value = "目录路径", name = "catalogPath", required = true) @RequestParam String catalogPath,
                                                  @ApiParam(value = "开始时间", name = "startTime") @RequestParam(required = false) Long startTime,
                                                  @ApiParam(value = "结束时间", name = "endTime") @RequestParam(required = false) Long endTime) throws Exception {
        ResponseMsg<List<FileDto>> responseMsg = new ResponseMsg<>();
        List<FileDto> queryRespBean = fileService.getFileList(fileName, catalogPath, startTime, endTime);
        responseMsg.setResponseBody(queryRespBean);
        return responseMsg;
    }

    @DeleteMapping("/deleteFileByPaths")
    @ApiOperation(value = "删除文件")
    @ApiParam(value = "文件路径(多个逗号分隔)", name = "filePath", required = true)
    public ResponseMsg<Boolean> deleteFileByPaths(@RequestBody FileDto fileDto) throws Exception {
        ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(fileService.deleteFileByPaths(fileDto.getFilePath()));
        return responseMsg;
    }

    @GetMapping("/getCatalogTree")
    @ApiOperation(value = "查询目录树")
    @ApiParam(value = "父目录路径", name = "parentCatalogPath")
    public ResponseMsg<CatalogDto> getCatalogTree(@RequestParam(required = false) String parentCatalogPath) throws Exception {
        ResponseMsg<CatalogDto> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(fileService.getCatalogTree(parentCatalogPath));
        return responseMsg;
    }

    @GetMapping("/getFilesByTemplate")
    @ApiOperation(value = "获取模板对应的文件")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "目录路径", name = "filePath", required = true),
            @ApiImplicitParam(value = "模板id", name = "templateId", required = true)
    })
    public ResponseMsg<List<String>> getFilesByTemplate(@RequestParam(required = false) String filePath,
                                                        @RequestParam String templateId) throws Exception {
        ResponseMsg<List<String>> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(fileService.getFilesByTemplate(filePath, templateId));
        return responseMsg;
    }

    @DeleteMapping("/deleteCatalogByPath")
    @ApiOperation(value = "删除目录")
    @ApiParam(value = "目录路径", name = "catalogPath", required = true)
    public ResponseMsg<Boolean> deleteCatalogByPath(@RequestBody CatalogDto catalogDto) throws Exception {
        ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(fileService.deleteCatalogByPath(catalogDto.getCatalogPath()));
        return responseMsg;
    }

    @PostMapping("/saveCatalog")
    @ApiOperation(value = "创建目录")
    @ApiParam(value = "CatalogDto", name = "catalogDto")
    public ResponseMsg<Boolean> saveCatalog(@RequestBody CatalogDto catalogDto) throws Exception {
        ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(fileService.saveCatalog(catalogDto));
        return responseMsg;
    }

    @PostMapping("/saveCatalogTemplate")
    @ApiOperation(value = "目录关联模板")
    @ApiParam(value = "CatalogTemplateDTO", name = "catalogTemplateDTO")
    public ResponseMsg<Boolean> saveCatalogTemplate(@RequestBody CatalogTemplateDTO catalogTemplateDTO) throws Exception {
        ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(fileService.saveCatalogTemplate(catalogTemplateDTO));
        return responseMsg;
    }

    @PostMapping("/cancelFileTemplate")
    @ApiOperation(value = "取消文件关联模板")
    @ApiParam(value = "CatalogTemplateDTO", name = "catalogTemplateDTO")
    public ResponseMsg<Boolean> cancelFileTemplate(@RequestBody CatalogTemplateDTO catalogTemplateDTO) throws Exception {
        ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(fileService.cancelFileTemplate(catalogTemplateDTO));
        return responseMsg;
    }

    @GetMapping("/getFileAttribute")
    @ApiOperation(value = "查看文件属性")
    @ApiParam(value = "文件路径", name = "filePath", required = true)
    public ResponseMsg<FileDto> getFileAttribute(@RequestParam String filePath) throws Exception {
        ResponseMsg<FileDto> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(fileService.getFileAttribute(filePath));
        return responseMsg;
    }

    @GetMapping("/downloadFile")
    @ApiOperation(value = "下载文件")
    @ApiParam(value = "文件路径", name = "filePath", required = true)
    public void downloadFile(@RequestParam String filePath, HttpServletRequest request, HttpServletResponse response) {
        try {
            fileCommonService.downloadFile(filePath, request, response);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }
    }

    @ApiOperation(value = "重命名文件")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "源文件名全路径", name = "srcPath", required = true),
            @ApiImplicitParam(value = "目的文件名全路径", name = "dstPath", required = true)
    })
    @GetMapping("/rename")
    public ResponseMsg<Boolean> rename(@RequestParam String srcPath, @RequestParam String dstPath) throws Exception {
        ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(fileService.rename(srcPath, dstPath));
        return responseMsg;
    }

    @GetMapping("/getCatalogTreeByDatasourceId")
    @ApiOperation(value = "查询关联模板的文件目录")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "数据源ID", name = "datasourceId", required = true),
            @ApiImplicitParam(value = "目录路径", name = "parentCatalogPath")
    })
    public ResponseMsg<CatalogDto> getCatalogTreeByDatasourceId(@RequestParam String datasourceId,
                                                                @RequestParam String parentCatalogPath) throws Exception {
        ResponseMsg<CatalogDto> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(fileService.getCatalogTreeByDatasourceId(datasourceId, parentCatalogPath));
        return responseMsg;
    }

    @GetMapping("/getChunkSize")
    @ApiOperation(value = "获取分片大小")
    public ResponseMsg<Long> getChunkSize() {
        ResponseMsg<Long> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(fileCommonService.getChunkSize());
        return responseMsg;
    }

    @GetMapping("/getUploadType")
    @ApiOperation(value = "获取上传类型")
    public ResponseMsg<Boolean> getUploadType() {
        ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(fileCommonService.getUploadType());
        return responseMsg;
    }

    @PostMapping("/checkFileExist")
    @ApiOperation(value = "判断文件是否存在")
    @ApiParam(value = "上传文件名列表", name = "fileList", required = true)
    public ResponseMsg<Map<String, Boolean>> checkFileExist(@RequestBody Map<String, Object> map) throws Exception {
        ResponseMsg<Map<String, Boolean>> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(fileCommonService.checkFileExist(map));
        return responseMsg;
    }

    @PostMapping("/generateTemplate")
    @ApiOperation(value = "生成模板")
    @ApiParam(value = "catalogTemplateDTO", name = "catalogTemplateDTO")
    public ResponseMsg<Boolean> generateTemplate(@RequestBody CatalogTemplateDTO catalogTemplateDTO) {
        ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(fileService.generateTemplate(catalogTemplateDTO));
        return responseMsg;
    }

    @GetMapping("/deleteCacheData")
    @ApiOperation(value = "删除缓存数据")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "hdfsPath", name = "hdfsPath", required = true),
            @ApiImplicitParam(value = "fileName", name = "fileName", required = true),
            @ApiImplicitParam(value = "fileMd5", name = "fileMd5", required = true)
    })
    public ResponseMsg<Boolean> deleteCacheData(@RequestParam String hdfsPath, @RequestParam String fileName,
                                                @RequestParam String fileMd5) throws Exception {
        ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(fileService.deleteCacheData(hdfsPath, fileName, fileMd5));
        return responseMsg;
    }

    @GetMapping("/deleteCacheDataByKey")
    @ApiOperation(value = "删除缓存数据")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "key", name = "key", required = true)
    })
    public ResponseMsg<Boolean> deleteCacheDataByKey(@RequestParam String key) throws Exception {
        ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(fileService.deleteCacheDataByKey(key));
        return responseMsg;
    }

    @GetMapping("/deleteRedisData")
    @ApiOperation(value = "删除redis缓存数据")
    public ResponseMsg<Boolean> deleteRedisData(String key) {
        ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();
        redisCacheHelper.del(key);
        responseMsg.setResponseBody(true);
        return responseMsg;
    }

}